//
//  UIView.swift
//  tverify
//
//  Created by changlei on 2023/8/15.
//

import Foundation
import Flutter

class UICustomView: UIView {
    private var plugin: TverifyPlugin!
    private var arguments: [String: Any]!
    
    convenience init(_ arguments: [String: Any], plugin: TverifyPlugin) {
        self.init()
        self.plugin = plugin
        self.arguments = arguments
        let type = arguments["type"] as! String
        
        var subview: UIView
        if type == "UITextView" {
            subview = toTextView()
        } else if type == "UIButton" {
            subview = toButton()
        } else if type == "UIImageView" {
            subview = toImageView()
        } else if type == "UIViewGroup" {
            subview = toViewGroup()
        } else {
            subview = UIView.init()
        }
        subview = configEdgeInsets(subview)
        configTapEvent(subview)
        self.addSubview(subview)
        self.clipsToBounds = true
        self.frame = subview.frame
        subview.frame = subview.bounds
    }
    
    private func toTextView() -> UIView {
        let left = arguments["left"] as! CGFloat
        let top = arguments["top"] as! CGFloat
        let width = arguments["width"] as! CGFloat
        var height = arguments["height"] as! CGFloat
        let title = arguments["title"] as! String
        let titleFont = toUIFont(arguments["titleFont"] as! [String: Any])
        let titleColor = toUIColor(arguments["titleColor"] as! [String: Any])
        let textAlignment = arguments["textAlignment"] as? Int
        let lines = arguments["lines"] as! Int
        let isSingleLine = arguments["isSingleLine"] as! Bool
        let isShowUnderline = arguments["isShowUnderline"] as! Bool
        
        let label = configView(UILabel.init())
        label.text = title
        label.textColor = titleColor
        if let textAlignment = tryToNSTextAlignment(textAlignment) {
            label.textAlignment = textAlignment
        }
        label.font = titleFont
        label.numberOfLines = lines
        if !isSingleLine {
            label.numberOfLines = 0
            let textSize = (label.text! as NSString).boundingRect(
                with: CGSize(width: width, height: height),
                options: NSStringDrawingOptions.truncatesLastVisibleLine,
                attributes: [NSAttributedString.Key.font: UIFont.systemFont(ofSize: 20)],
                context: nil
            ).size
            height = textSize.height
        }
        if isShowUnderline {
            let attributes = [NSAttributedString.Key.underlineStyle: NSUnderlineStyle.single.rawValue]
            label.attributedText = NSMutableAttributedString(string: title, attributes: attributes)
        }
        label.frame = CGRectMake(left, top, width, height)
        return label
    }
    
    private func toButton() -> UIView {
        let id = arguments["id"] as! String
        let left = arguments["left"] as! CGFloat
        let top = arguments["top"] as! CGFloat
        let width = arguments["width"] as! CGFloat
        let height = arguments["height"] as! CGFloat
        let title = arguments["title"] as! String
        let titleFont = toUIFont(arguments["titleFont"] as! [String: Any])
        let titleColor = toUIColor(arguments["titleColor"] as! [String: Any])
        let textAlignment = arguments["textAlignment"] as? Int
        let btnNormalImage = tryToUIImage(arguments["btnNormalImage"] as? [String: Any])
        let btnPressedImage = tryToUIImage(arguments["btnPressedImage"] as? [String: Any])
        let isShowUnderline = arguments["isShowUnderline"] as! Bool
        
        let button = configView(UIButton.init())
        if let insets = tryToUIEdgeInsets(arguments["padding"] as? [String: Any]) {
            button.contentEdgeInsets = insets
        }
        button.setTitle(title, for: .normal)
        button.setTitle(title, for: .highlighted)
        button.setTitleColor(titleColor, for: .normal)
        if let textAlignment = tryToUIControlContentHorizontalAlignment(textAlignment) {
            button.contentHorizontalAlignment = textAlignment
        }
        button.titleLabel?.font = titleFont
        if isShowUnderline {
            let attributes = [NSAttributedString.Key.underlineStyle: NSUnderlineStyle.single.rawValue]
            button.titleLabel?.attributedText = NSMutableAttributedString(string: title, attributes: attributes)
        }
        button.frame = CGRectMake(left, top, width, height)
        button.isUserInteractionEnabled = arguments["isClickEnable"] as! Bool
        button.addTarget(self, action: #selector(clickButtonAction(_:)), for: .touchUpInside)
        let pressedImage = btnPressedImage ?? btnNormalImage
        if let normalImage = btnNormalImage {
            button.setBackgroundImage(normalImage, for: .normal)
        }
        if let pressedImage = pressedImage {
            button.setBackgroundImage(pressedImage, for: .highlighted)
            button.setBackgroundImage(pressedImage, for: .selected)
        }
        return button
    }
    
    private func toImageView() -> UIView {
        let imageView = configView(UIImageView.init())
        if let src = tryToUIImage(arguments["src"] as! [String: Any]?) {
            imageView.image = src
        }
        if let fit = arguments["fit"] as! Int? {
            let boxFit = BoxFit.init(rawValue: fit)
            switch boxFit {
            case .contain:
                imageView.contentMode = .scaleAspectFit
                break
            case .cover:
                imageView.contentMode = .scaleAspectFill
                break
            case .fill:
                imageView.contentMode = .scaleToFill
                break
            case .fitHeight:
                imageView.contentMode = .center
                break
            case .fitWidth:
                imageView.contentMode = .center
                break
            case .scaleDown:
                imageView.contentMode = .bottom
                break
            default:
                break
            }
        }
        return imageView
    }
    
    private func toViewGroup() -> UIView {
        let view = configView(UIView.init())
        if let children = arguments["children"] as! [[String:Any]]? {
            for child in children {
                view.addSubview(UICustomView.init(child, plugin: plugin))
            }
        }
        view.clipsToBounds = true
        return view
    }
    
    private func configTapEvent(_ view: UIView) {
        let id = arguments["id"] as! String
        let left = arguments["left"] as! CGFloat
        let top = arguments["top"] as! CGFloat
        let width = arguments["width"] as! CGFloat
        let height = arguments["height"] as! CGFloat
        if arguments["isClickEnable"] as! Bool, !(view is UIButton) {
            let tag = NSString(string: "\(Int(left + top + width + height))")
            view.isUserInteractionEnabled = true
            let singleTapGestureRecognozer = UITapGestureRecognizer(target: self, action: #selector(clickLabelAction(_:)))
            singleTapGestureRecognozer.numberOfTapsRequired = 1
            view.addGestureRecognizer(singleTapGestureRecognozer)
        }
    }
    
    private func configView<T: UIView>(_ view: T) -> T {
        let left = arguments["left"] as! CGFloat
        let top = arguments["top"] as! CGFloat
        let width = arguments["width"] as! CGFloat
        let height = arguments["height"] as! CGFloat
        view.frame = CGRectMake(left, top, width, height)
        
        let backgroundColor = tryToUIColor(arguments["backgroundColor"] as? [String: Any])
        view.backgroundColor = backgroundColor ?? .clear
        
        if let backgound = tryToUIImage(arguments["background"] as? [String: Any]) {
            let backgroundImageView = UIImageView(image: backgound)
            backgroundImageView.contentMode = .scaleToFill
            backgroundImageView.frame = view.bounds
            view.addSubview(backgroundImageView)
        }
        return view
    }
    
    private func configEdgeInsets(_ view: UIView) -> UIView {
        if let insets = tryToUIEdgeInsets(arguments["padding"] as? [String: Any]), !(view is UIButton) {
            let parent = UIView(frame: view.frame)
            view.frame = parent.bounds.inset(by: insets)
            parent.addSubview(view)
            parent.clipsToBounds = true
            return parent
        } else {
            return view
        }
    }
    
    @objc func clickLabelAction(_ sender: UITapGestureRecognizer) {
        plugin.onClickListener(id: arguments["id"] as! String)
    }
    
    @objc func clickButtonAction(_ sender: UIButton) {
        plugin.onClickListener(id: arguments["id"] as! String)
    }
}

private enum BoxFit : Int {
    case fill = 0,
         contain = 1,
         cover = 2,
         fitWidth = 3,
         fitHeight = 4,
         none = 5,
         scaleDown = 6;
}
